package auctionServer;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.Socket;
import java.rmi.Naming;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.Vector;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;

import common.AuctionEvent;
import common.BidEvent;
import common.UserEvent;
import common.rmi.RemoteAnalyzer;
import common.RegistryManagement;

import auctionServer.utilities.Auction;
import auctionServer.utilities.GroupBid;
import auctionServer.utilities.HMACCreator;
import auctionServer.utilities.TcpServerConnection;
import auctionServer.utilities.User;


public class ServerReplica implements Runnable{
	
	public class BooleanResult {
	    private boolean result;

	    public void setResult(boolean value) { result = value; }
	    public boolean getResult() { return result; }
	}

	private TcpServerConnection clientConnection;

	private String userName="";
	private String loggedInUser="Nobody";
	private Hashtable<String, User> logged;
	private Vector<Auction> auctions;
	private List<GroupBid> groupBids;
	private String analyticsServerBindingName;
	private RemoteAnalyzer analyticsServer;
	private String serverKeyFile;
	private String clientsKeyDir;
	private boolean isSecureChanel;
	private Key sharedSecretKey=null;
	private BufferedReader reader;
	
	public ServerReplica(int tcpPort, Socket connectedClient, Hashtable<String, User> logged, Vector<Auction> auctions, String analyticsServerBindingName, String serverKeyFile, String clientsKeyDir, BufferedReader reader, List<GroupBid> groupBids) {
		this.clientConnection=new TcpServerConnection(tcpPort,connectedClient);
		this.logged=logged;
		this.auctions=auctions;
		this.analyticsServerBindingName=analyticsServerBindingName;
		this.serverKeyFile=serverKeyFile;
		this.clientsKeyDir=clientsKeyDir;
		this.reader = reader;
		this.sharedSecretKey=defaultKey();
		this.groupBids=groupBids;
	}
	
	@Override
	public void run() {
		isSecureChanel = false;

		StringBuilder registryHost = new StringBuilder(); 
		StringBuilder registryPortStr = new StringBuilder(); 
		RegistryManagement.getRegistryInfo(registryHost, registryPortStr);
		int registryPort = Integer.valueOf(registryPortStr.toString());
		Scanner stringReader = null;
		String addressRMI = "rmi://" + registryHost.toString() + ":" + String.valueOf(registryPort) + "/";
		try {
			analyticsServer=(RemoteAnalyzer)Naming.lookup(addressRMI + analyticsServerBindingName);
		} catch (Exception e1) {
			System.out.println("Cannot find the Analytics Server");
			analyticsServer=null;
		}
		while(true){
			/*
			 * Setting the userLine and command for successive operation
			 */
			byte[] userLine=clientConnection.getMessage();
			
			try{
				stringReader=new Scanner(new String(userLine));
			}catch(java.lang.NullPointerException e){
				clientConnection.disconnect();
				doLogout();
				break;
			}
			String command = "";
			try{
				command=stringReader.next();
			}catch(java.lang.NullPointerException e){
				clientConnection.disconnect();
				doLogout();
				break;
			}
			
			if(command.equals("!list")){	
				doList();
			}else if(command.equals("!isAlive?")){
				clientConnection.appendMessage("yes".getBytes());
			}
			else{
				if (isSecureChanel)
				{
					String responseMessage = "";
					try {
						Cipher aesCipher = Cipher.getInstance("AES/CTR/NoPadding");
						aesCipher.init(Cipher.DECRYPT_MODE, logged.get(userName).getKey(), logged.get(userName).getivSpec());
						responseMessage = new String(aesCipher.doFinal(userLine));
					} catch (NoSuchAlgorithmException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (NoSuchPaddingException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (InvalidKeyException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (InvalidAlgorithmParameterException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IllegalBlockSizeException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (BadPaddingException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					try{
						stringReader=new Scanner(new String(responseMessage));
					}catch(java.lang.NullPointerException e){
						clientConnection.disconnect();
						doLogout();
						break;
					}
					
					command = "";
					try{
						command=stringReader.next();
					}catch(java.lang.NullPointerException e){
						clientConnection.disconnect();
						doLogout();
						break;
					}
					
					if(loggedInUser.equals("Nobody")){
						continue;
					}else{
						
						if(command.equals("!logout")){
							doLogout(stringReader.next());
						}
				
						else if(command.equals("!create")){
							doCreate(stringReader.nextInt(), stringReader.next());
						}
						
						else if(command.equals("!bid")){
							doBid(stringReader.nextInt(), stringReader.nextInt());
						}
						
						else if(command.equals("!groupbid")){
							doGroupBid(stringReader.nextInt(), stringReader.nextInt());
						}

						else if(command.equals("!confirm")){
							doConfirm(stringReader.nextInt(), stringReader.nextInt(), stringReader.next());
						}
						
						else if(command.equals("!signedBid")){
							doSignedBid(stringReader.nextInt(), stringReader.nextInt(), stringReader.next(), stringReader.next());
						}
						else if(command.equals("!getClientList")){
							doGetClientsList();
						}
					}					
				}
				else
				{
					byte[] clearUserLine = "".getBytes();
					try {
						@SuppressWarnings("resource")
						PEMReader in = new PEMReader(new FileReader(serverKeyFile), new PasswordFinder() {
							@Override
							public char[] getPassword() {
								char[] res = "".toCharArray();
								// reads the password from standard input for decrypting the private key
								System.out.println("Enter pass phrase:");
								try {
									res = reader.readLine().toCharArray();
								} catch (IOException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
								return res;
							}
						});
						KeyPair keyPair = (KeyPair) in.readObject();
						PrivateKey privateKey = keyPair.getPrivate();
						Cipher rsaCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding");
						rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
						clearUserLine = rsaCipher.doFinal(userLine);
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (InvalidKeyException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (NoSuchAlgorithmException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (NoSuchPaddingException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IllegalBlockSizeException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (BadPaddingException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					try{
						stringReader=new Scanner(new String(clearUserLine));
					}catch(java.lang.NullPointerException e){
						clientConnection.disconnect();
						doLogout();
						break;
					}
					try{
						command=stringReader.next();
					}catch(java.lang.NullPointerException e){
						clientConnection.disconnect();
						doLogout();
						break;
					}
					
					if(command.equals("!login")){
						userName=stringReader.next();
						int tcpPort=stringReader.nextInt();
						String clientChallenge=stringReader.next();
						doLogin(userName, tcpPort, clientChallenge);
					}
				}
			}
		}
		stringReader.close();
	}
	
	private void doLogin(String userName,int tcpPort, String clientChallenge){
		SecretKey key = null;
		IvParameterSpec ivSpec = null;
		try {
			KeyGenerator generator = KeyGenerator.getInstance("AES");
			generator.init(256); 
			key = generator.generateKey();
			byte[] ivSpec1 = new byte[]
	                {
	                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	                };
			ivSpec = new IvParameterSpec(ivSpec1);
		} catch (NoSuchAlgorithmException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if(logged.containsKey(userName)){
			if(logged.get(userName).getValue()==true){
				try {
					@SuppressWarnings("resource")
					PEMReader in = new PEMReader(new FileReader(clientsKeyDir + userName + ".pub.pem"));
					PublicKey publicKey = (PublicKey) in.readObject();
					Cipher aesCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding");
					aesCipher.init(Cipher.ENCRYPT_MODE, publicKey);
					byte[] cipherMessage = aesCipher.doFinal("already logged in".getBytes());
					
					clientConnection.appendMessage(cipherMessage);

				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (NoSuchAlgorithmException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (NoSuchPaddingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvalidKeyException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalBlockSizeException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (BadPaddingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else{
				logged.get(userName).setValue(true);
				logged.get(userName).setTCPPort(tcpPort);
				logged.get(userName).setKey(key);
				logged.get(userName).setivSpec(ivSpec);
				doLogin_Process(userName, clientChallenge, key, ivSpec);
			}
		}else{
			logged.put(userName, new User(true, userName, tcpPort, key, ivSpec));
			doLogin_Process(userName, clientChallenge, key, ivSpec);
		}
	}
	
	private void doLogin_Process(String userName, String clientChallenge, SecretKey key, IvParameterSpec ivSpec){
		try {
			analyticsServer.processEvent(new UserEvent("USER_LOGIN", userName));
		} catch (Exception e) {
			System.out.println("Connection error to analyticsServer");
		}
		
		SecureRandom secureRandom = new SecureRandom(); 
		byte[] challengeNumber = new byte[32]; 
		secureRandom.nextBytes(challengeNumber);
		byte[] base64ChallengeNumber = Base64.encode(challengeNumber);
		
		byte[] base64Key = Base64.encode(key.getEncoded());
		byte[] base64IV = Base64.encode(ivSpec.getIV());
		byte[] message= ("!ok "+clientChallenge+" "+(new String(base64ChallengeNumber))+" "+(new String(base64Key))+" "+(new String(base64IV))).getBytes();
		//RSA cipher
		try {
			@SuppressWarnings("resource")
			PEMReader in = new PEMReader(new FileReader(clientsKeyDir + userName + ".pub.pem"));
			PublicKey publicKey = (PublicKey) in.readObject();
			Cipher rsaCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding");
			rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
			byte[] cipherMessage = rsaCipher.doFinal(message);
			
			clientConnection.appendMessage(cipherMessage);
			
			byte[] userLine=clientConnection.getMessage();
			
			Cipher aesCipher = Cipher.getInstance("AES/CTR/NoPadding");
			aesCipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
			String responseMessage = new String(aesCipher.doFinal(userLine));
			
			if (responseMessage.equals(new String(base64ChallengeNumber)))
			{
				loggedInUser=userName;
				isSecureChanel = true;
				sharedSecretKey=readKey();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void doList(){
		String list="";
		int iteration=0;
		SimpleDateFormat format = new SimpleDateFormat();
		
		for(Auction auction: auctions){
			if(auction.expired()==false){
				list=list+"Auction with id "+auction.getId()+" '"+auction.getDescription()+"' "+auction.getOwner()+" "+format.format(auction.getFrom().getTime())+" "+auction.getCurrentPrice()+" "+auction.getWinningBidder()+"\n";
				iteration++;
			}
		}
		HMACCreator hashCreator= new HMACCreator(iteration + "@" + list, sharedSecretKey);
		list=hashCreator.append();
		clientConnection.appendMessage((list).getBytes());
	}

	private void doLogout(){
		if(loggedInUser.equals("Nobody")){
			
		}else{
			logged.get(loggedInUser).setValue(false);
			loggedInUser="Nobody";
			isSecureChanel = false;
			try {
				analyticsServer.processEvent(new UserEvent("USER_LOGOUT", userName));
			} catch (Exception e) {
				System.out.println("Connection error to analyticsServer");
			}
			try{
				clientConnection.appendMessage(getEncryptedMessageByASE("logged out".getBytes()));
			}catch(Exception e){
				System.out.println("Cannot append the logged out message to the client Socket");
			}
		}
	}
	
	private void doLogout(String sessionUser){
		if(loggedInUser.equals("Nobody")){
			
		}else if(loggedInUser.equals(sessionUser)){
			logged.get(loggedInUser).setValue(false);
			loggedInUser="Nobody";
			try {
				analyticsServer.processEvent(new UserEvent("USER_LOGOUT", userName));
			} catch (Exception e) {
				System.out.println("Connection error to analyticsServer");
			}
			try{
				clientConnection.appendMessage(getEncryptedMessageByASE("logged out".getBytes()));
			}catch(Exception e){
				System.out.println("Cannot append the logged out message to the client Socket");
			}

		}else{
			clientConnection.appendMessage(getEncryptedMessageByASE("mismatch".getBytes()));
		}
	}
	
	private void doCreate(int duration,String description){
		SimpleDateFormat format = new SimpleDateFormat();
		auctions.add(new Auction(duration, description, loggedInUser));
		try {
			analyticsServer.processEvent(new AuctionEvent((long)auctions.lastElement().getId(), "AUCTION_STARTED"));
			
		} catch (Exception e) {
			System.out.println("Connection error to analyticsServer");
		}
		clientConnection.appendMessage(getEncryptedMessageByASE(("created "+auctions.lastElement().getId()+" "+format.format(auctions.lastElement().getTo().getTime())).getBytes()));
	}
	
	private void doGroupBid(int auctionID, int price){
		
		boolean auctionFound=false;
		
		for(Auction auction: auctions){
			if(auction.getId()==auctionID){
				auctionFound = true;
			}
		}
		
		if (auctionFound)
		{
			Lock lock = new ReentrantLock();
			lock.lock();

			boolean isDone=false;
			
			String message="";
			for(GroupBid groupBid: groupBids){
				if (!groupBid.getIsBidDone()){
					if(groupBid.getAuctionID()==auctionID&&groupBid.getBidder()==loggedInUser){
						groupBid.setPrice(price);
						isDone = true;
						message = "GroupBid request was updated";
						break;
					}
					else if (groupBid.getAuctionID()==auctionID){
						isDone = true;
						message = "GroupBid rejected, this auction has been bidded before by group";
						break;
					}
				}
					
			}
			if (!isDone){
				int loggedInUsersCount = 0;
				int groupBidCount = 0;
				int maxRejectedCount = 0;
				for(GroupBid groupBid: groupBids){
					if (!groupBid.getIsBidDone()){
						groupBidCount++;
					}
				}
				for(User user: logged.values()){
					if (user.getValue())
						loggedInUsersCount++;
					if ((user.getRejectedCount() > maxRejectedCount) && (!user.getName().equals(loggedInUser)))
						maxRejectedCount = user.getRejectedCount(); 
				}
				
				if (groupBidCount < loggedInUsersCount)
				{
					if (logged.get(loggedInUser).getRejectedCount() >= maxRejectedCount){
						GroupBid groupBid = new GroupBid(loggedInUser, auctionID, price);
						groupBids.add(groupBid);
						clientConnection.appendMessage(getEncryptedMessageByASE("GroupBid request was saved".getBytes()));						
					}
					else {
						logged.get(loggedInUser).setRejectedCount(logged.get(loggedInUser).getRejectedCount() + 1);
						clientConnection.appendMessage(getEncryptedMessageByASE("GroupBid rejected, preventing starvation".getBytes()));
					}
				}
				else{
					logged.get(loggedInUser).setRejectedCount(logged.get(loggedInUser).getRejectedCount() + 1);
					clientConnection.appendMessage(getEncryptedMessageByASE("GroupBid rejected".getBytes()));
				}
			}
			else
				clientConnection.appendMessage(getEncryptedMessageByASE(message.getBytes()));
			lock.unlock();
		}
		else
			clientConnection.appendMessage(getEncryptedMessageByASE("Auction not found".getBytes()));
	}

	private void doConfirm(int auctionID, int price, String bidder){
		
		boolean found=false;
		
		for(GroupBid groupBid: groupBids){
			if (!groupBid.getIsBidDone()){
				if(groupBid.getAuctionID()==auctionID&&groupBid.getPrice()==price&&groupBid.getBidder().equals(bidder)){
					found = true;
					if (groupBid.addConfirm(loggedInUser, logged.values(), groupBids)){
						while (1==1){
							if (groupBid.getConfirmCount()>=2)
								break;
						}
						
						//do bid
						Lock lock = new ReentrantLock();
		    			lock.lock();
		    			if (!groupBid.getIsBidDone()){
		    				BooleanResult result = new BooleanResult();
							byte[] response = doBidProcess(auctionID, price, result);
							groupBid.setBidResult(result.getResult());
							groupBid.setBidResultResponse(response);
							groupBid.setIsBidDone(true);
		    			}
						if (groupBid.getBidResult())
							clientConnection.appendMessage(getEncryptedMessageByASE("!confirmed".getBytes()));
						else
							clientConnection.appendMessage(getEncryptedMessageByASE(("!rejected " + (new String(groupBid.getBidResultResponse()))).getBytes()));	    			
		    			lock.unlock();
					}
					else{
						clientConnection.appendMessage(getEncryptedMessageByASE("!rejected GroupBid was not confirmed".getBytes()));
					}
					break;
				}
			}
		}
		if (!found)
			clientConnection.appendMessage(getEncryptedMessageByASE("!rejected GroupBid not found".getBytes()));
	}

	private void doBid(int auctionId, int amount){
		BooleanResult result = new BooleanResult();
		clientConnection.appendMessage(getEncryptedMessageByASE(doBidProcess(auctionId, amount, result)));
	}
	
	private byte[] doBidProcess(int auctionId, int amount, BooleanResult result){
		
		boolean found=false;
		byte[] res="".getBytes();
		result.setResult(false);
		
		for(Auction auction: auctions){
			if(auction.getId()==auctionId&&auction.expired()==false){
				if(auction.bid(loggedInUser, amount)){
					result.setResult(true);
					res = ("bid accepted@" + auction.getDescription()).getBytes();
					try {
						analyticsServer.processEvent(new BidEvent("BID_PLACED",userName,(long)auctions.lastElement().getId(),(double)amount));
						
					} catch (Exception e) {
						System.out.println("Connection error to analyticsServer");
					}
				}else{
					res = ("bid denied@"+auction.getDescription()+". Current highest bid: "+auction.getCurrentPrice()).getBytes();
				}
				found=true;
				break;
			}
		}
		if(found==false){
			res = "not found".getBytes();
		}
		return res;
	}

	private byte[] getEncryptedMessageByASE(byte[] message)
	{
		byte[] responseMessage = "".getBytes();
		try {
			Cipher aesCipher = Cipher.getInstance("AES/CTR/NoPadding");
			aesCipher.init(Cipher.ENCRYPT_MODE, logged.get(userName).getKey(), logged.get(userName).getivSpec());
			responseMessage = aesCipher.doFinal(message);
		} catch (NoSuchAlgorithmException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (NoSuchPaddingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return responseMessage;
	}

	private void doSignedBid(int auctionId, int amount, String frstUserSign, String scndUserSign){
		//Signature integrity will be checked.
		boolean valid=false;
		String[] first=frstUserSign.split(":");
		String[] second=scndUserSign.split(":");
		Calendar timestamp1=Calendar.getInstance();
		Calendar timestamp2=Calendar.getInstance();
		timestamp1.setTimeInMillis(Long.parseLong(first[1], 10));
		timestamp2.setTimeInMillis(Long.parseLong(second[1], 10));

		try {
			if(verifySignature(("!timestamp "+auctionId+" "+amount+" "+first[1]).getBytes(),readPublicKey(first[0]),first[2].getBytes())){
				if(verifySignature(("!timestamp "+auctionId+" "+amount+" "+second[1]).getBytes(),readPublicKey(second[0]),second[2].getBytes())){
					valid=true;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(valid){
			if(timestamp1.equals(timestamp2)){
				
			}else{
				timestamp1=Calendar.getInstance();
				timestamp1.setTimeInMillis((timestamp1.getTimeInMillis()+timestamp2.getTimeInMillis())/2);
			}
			
			boolean found=false;
			
			for(Auction auction: auctions){
				if(auction.getId()==auctionId&&auction.expired()==false){
					if(auction.signedBid(loggedInUser, amount, timestamp1)){
						clientConnection.appendMessage(getEncryptedMessageByASE(("bid accepted@" + auction.getDescription()).getBytes()));
						try {
							analyticsServer.processEvent(new BidEvent("BID_PLACED",userName,(long)auctions.lastElement().getId(),(double)amount));
							
						} catch (Exception e) {
							System.out.println("Connection error to analyticsServer");
						}
					}else{
						clientConnection.appendMessage(getEncryptedMessageByASE(("bid denied@"+auction.getDescription()+". Current highest bid: "+auction.getCurrentPrice()).getBytes()));
					}
					found=true;
					break;
				}
			}
			if(found==false){
				clientConnection.appendMessage(getEncryptedMessageByASE("not found".getBytes()));
			}
			
		}else{
			//DO NOTHING!
		}

	}

	private boolean verifySignature(byte[] data, PublicKey key, byte[] sig) throws Exception{
	    Signature signer = Signature.getInstance("SHA512withRSA");
	    signer.initVerify(key);
	    signer.update(data);
	    return (signer.verify(sig));
	}
	
	private PublicKey readPublicKey(String userName) throws Exception{
		PEMReader in = new PEMReader(new FileReader(clientsKeyDir+userName+".pub.pem")); 
		PublicKey publicKey = (PublicKey) in.readObject();
		in.close();
		return publicKey;
	}
	
	private void doGetClientsList(){
		clientConnection.appendMessage(getEncryptedMessageByASE(Server.getClientList().getBytes()));
	}
	
	private Key readKey(){
		byte[] keyBytes = new byte[1024];
		//TODO insert path!
		String pathToSecretKey =clientsKeyDir+userName+".key";
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(pathToSecretKey);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fis.read(keyBytes);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fis.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		byte[] input = Hex.decode(keyBytes);
		// make sure to use the right ALGORITHM for what you want to do 
		// (see text) 
		
		return new SecretKeySpec(input,"AES");
		
		
	}

	private Key defaultKey(){
		byte[] keyBytes = new byte[1024];
		//TODO insert path!
		String pathToSecretKey =clientsKeyDir+"default.key";
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(pathToSecretKey);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fis.read(keyBytes);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fis.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		byte[] input = Hex.decode(keyBytes);
		// make sure to use the right ALGORITHM for what you want to do 
		// (see text) 
		
		return new SecretKeySpec(input,"AES");
		
		
	}

}
